package com.sky.ascept;

import com.sky.anno.AutoFill;
import com.sky.anno.OperationType;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.xml.crypto.dsig.SignatureMethod;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 这个类表示要对公共字段进行设置的切面类。
 * 这里用到的技术是反射技术（不熟悉的话，看一下Java基础反射知识点）
 * @author wangqi
 * @date 2023/12/27 15:28
 */
@Aspect
@Component
@Slf4j
public class AutoFillAscept {
    @Before("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.anno.AutoFill)")
    public void autoFill(JoinPoint joinPoint){
        /////////////////////重要////////////////////////////////////
        //解析：JoinPoint表示切入点（实际上就是要进行功能增强的方法）

        //1.获取方法对象
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        log.info("切入的方法：{}",methodSignature.toString());

        //2.获取到方法的参数（比如：Employee）
        //@AutoFill(OperationType.UPDATE)
        //void update(Employee employee);

        Object arg = joinPoint.getArgs()[0];

        //3.获取方法上的注解，以及注解上的属性
        AutoFill autoFill = methodSignature.getMethod().getAnnotation(AutoFill.class);
        OperationType operationType = autoFill.value();
        if(operationType == OperationType.INSERT){
            //添加操作（给要添加的目标参数设置创建时间、修改时间、创建人、修改人）
            try {
                //获取到要拦截的方法的参数的设置属性的方法。
                Method setCreateTimeMethod = arg.getClass().getMethod("setCreateTime", LocalDateTime.class);
                Method setUpdateTimeMethod = arg.getClass().getMethod("setUpdateTime", LocalDateTime.class);
                Method setCreateUserMethod = arg.getClass().getMethod("setCreateUser", Long.class);
                Method setUpdateUserMethod = arg.getClass().getMethod("setUpdateUser", Long.class);

                //执行方法
                setCreateTimeMethod.invoke(arg,LocalDateTime.now());
                setUpdateTimeMethod.invoke(arg,LocalDateTime.now());
                setCreateUserMethod.invoke(arg, BaseContext.getCurrentId());
                setUpdateUserMethod.invoke(arg,BaseContext.getCurrentId());
                log.info("=====添加时公共字段设置成功");

            } catch (Exception e) {
                throw new BaseException(MessageConstant.UNKNOWN_ERROR);
            }
        }else if(operationType == OperationType.UPDATE){
            //修改操作
            //添加操作（给要添加的目标参数设置创建时间、修改时间、创建人、修改人）
            try {
                //获取到要拦截的方法的参数的设置属性的方法。
                Method setUpdateTimeMethod = arg.getClass().getMethod("setUpdateTime", LocalDateTime.class);
                Method setUpdateUserMethod = arg.getClass().getMethod("setUpdateUser", Long.class);

                //执行方法
                setUpdateTimeMethod.invoke(arg,LocalDateTime.now());
                setUpdateUserMethod.invoke(arg,BaseContext.getCurrentId());
                log.info("=====修改时公共字段设置成功");
            } catch (Exception e) {
                throw new BaseException(MessageConstant.UNKNOWN_ERROR);
            }
        }
    }
}
